#pragma once
#include "..\..\CommLib\CommStructs.h"
#include "..\..\CommLib\PacketConven.h"
#include "..\Render\Render.h"
#include "..\..\Global\globaldef.h"
#include "Material.h"

struct tChannel {

	bool active;
	/*tCharBuffer m_Samplers[5];*/
	HMATERIAL m_hMaterials[5];
};

struct tPart {

	uint m_TriangleCount;
	byte* m_pTriangleData;
	Render::tShader* m_pShader;
	Render::tResource* m_pVertexBuffer;
	Render::tResource* m_pIndexBuffer;

	tChannel m_channels[3];

	//int GetShaderAttributes();
	tPart();
};

struct tInstanceChild {

	uint m_uv;
	Render::tResource* m_pBuffer;
	HMATERIAL m_pCookie;
	tCharBuffer m_childName;
	HMATERIAL m_hChannels[3];
};
	

class Model
{
public:
	
	enum TEXTURE_CHANNEL {

		liveview_color			= 0,
		liveview_normal			= 1,
		lv_aux		= 2,
		TEXTURE_COUNT	= 3
	};

	enum INSTANCE_CHANNEL {

		POSITION		= 0,
		ROTATION		= 1,
		SCALE			= 2,
		INSTANCE_COUNT	= 3
	};

private:

	/*
	Internal data fields
	*/
	std::vector<tPart> m_Parts;
	
	bool m_deformation;
	float m_deformationScale;
	Render::tResource* m_pDeformationStreamBuffers[2];
	
	bool m_instanced;
	std::vector<tInstanceChild> m_instanceChildren;

	D3DXMATRIX m_World;
	tCharBuffer m_ID;

	void Render(Render::tResource* pInstanceBuffer, UINT instanceCount);
	bool UpdatePartGeometry(HeaderStructs::tGeometryPartHeader* pHeader, uint vertexFormat, byte* pGeometryPartData, uint partIndex);
	bool UpdatePartSamplers(HeaderStructs::tParametersPartHeader* pHeader, uint partIndex);
	void ReleasePart(uint partIndex);

	tInstanceChild* GetInstanceChild(tCharBuffer* pTarget);
	void ReleaseInstanceChild(tInstanceChild* pChild);

public:

	Model();
	Model(const tCharBuffer* pID);

	
	/*
	void SetShader(const std::string& shaderFilename, const int shaderFeatureSet, const int vertexFormat = -1);
	bool GetChildInstance(u_int index, Model** pInstanceChildOut, tProceduralData* pProceduralOut);
	bool AddChildInstancing(Model* pInstanceChild, HeaderStructs::tSurfaceTextureHeader* data, byte* pSurfaceTextureData);
	bool RemoveChildInstancing(Model* pInstanceChild);
	u_int ChildInstancingCount();*/
	
	void UpdateGeometry(HeaderStructs::tGeometryHeader* pHeader, byte* pGeometryData);
	void UpdateChannel(HeaderStructs::tChannelHeader* pHeader);
	void UpdateShader(HeaderStructs::tShaderHeader* pHeader, char* pData);
	void UpdateSampler(HeaderStructs::tSamplerHeader* pHeader);

	bool UpdateInstanceChild_Mask(HeaderStructs::tMaskHeader* pHeader, char* pData);
	bool UpdateInstanceChild_UV(HeaderStructs::tInstanceChildUV* pHeader);
	bool UpdateInstanceChild_Sampler(HeaderStructs::tInstanceChildSampler* pHeader);
	bool UpdateInstanceChild(HeaderStructs::tInstanceChildChange* pHeader);
	
	void UpdateParameters(HeaderStructs::tParametersHeader* pHeader);
	/*void UpdateDeformation(HeaderStructs::tDeformationHeader* pHeader);*/
	void UpdateInstancing(HeaderStructs::tInstanceHeader* pHeader, byte* pInstancingData);
	void UpdateTransform(tMatrix4 *pTransform);

	bool GetID(tCharBuffer* pOut);
	bool GetInfoGeometry(QuerysStructs::tGeometryHeader *pOut, QuerysStructs::tGeometryPartHeader **pOutParts, byte ***pOutTriangles);
	bool GetInfoInstancing(QuerysStructs::tInstancingHeader* pHeaderOut, QuerysStructs::tInstanceChildHeader* pChildrenOut);
	bool GetInfoDeformation(QuerysStructs::tDeformationHeader* pHeaderOut);
	bool GetInfoParameters(bool* pIsInstanced, bool* pIsDeformation);

	bool GetInstanceChild(tCharBuffer* pName, Model** pOut);
	bool GetTransform(tMatrix4 *pOut);

	void DrawInstanceChildren();
	void Draw();

	void Release();
};